package com.sina.shop.event;

import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ApplicationEventMulticaster;
import org.springframework.context.event.SimpleApplicationEventMulticaster;
import org.springframework.core.ResolvableType;

import java.util.concurrent.Executor;

/**
 * 这个类是 {@link ApplicationEventMulticaster} 的一个实现.
 * <p>
 * 当以下条件同时满足时将同步调用监听器
 * <ol>
 * <li>当 {@link ApplicationEvent } 为 {@link SinaEvent} 的实例</li>
 * <li>{@link SinaEvent#isSync()} 为 true} </li>
 * </ol>
 * 否则异步调用监听器.
 * </p>
 * <p>
 * 这个类的子类也应该遵循上述规则.
 * </p>
 * created  on 30/10/2017.
 */
public class SinaApplicationEventMulticaster extends SimpleApplicationEventMulticaster {


    @Override
    public void multicastEvent(ApplicationEvent event, ResolvableType eventType) {
        ResolvableType type = (eventType != null ? eventType : resolveDefaultEventType( event ));
        for (final ApplicationListener<?> listener : getApplicationListeners( event, type )) {
            if (event instanceof SinaEvent) {
                if (((SinaEvent) event).isSync()) {
                    // 同步调用
                    invokeListener( listener, event );
                } else {
                    defaultProcess( listener, event );
                }
            } else {
                defaultProcess( listener, event );
            }

        }
    }

    private void defaultProcess(final ApplicationListener<?> listener, final ApplicationEvent event) {
        Executor executor = getTaskExecutor();
        if (executor != null) {
            executor.execute( () -> invokeListener( listener, event ) );
        } else {
            invokeListener( listener, event );
        }
    }

    private ResolvableType resolveDefaultEventType(ApplicationEvent event) {
        return ResolvableType.forInstance( event );
    }
}
